package security;

use nginx;
use Switch;

our $combi;
our $user_agent; 
our $uri;

do 'rules.pl';
do 'jsprotect.pl';

use constant DEBUG => 1;

## get routine used for GET request for php backend
sub _common {
	my $r = shift;
	_prepare($r); # prepare request for easy parsing
	switch(_sql_injection($r)){
		case 1 { return _drop($r,"SQL injection") }
		case 2 { return _ban($r,"SQL injection") }
		case 3 { return _deny($r,"SQL injection") }
       	}
	switch(_sys_path($r)){
		case 1 { return _drop($r,"system path") }
		case 2 { return _ban($r,"system path") }
		case 3 { return _deny($r,"systen path") }
	}
	switch(_xss($r)){
		case 1 { return _drop($r,"XSS") }
		case 2 { return _ban($r,"XSS") }
		case 3 { return _deny($r,"XSS") }
	}
	switch(_user_agent($r)){
		case 1 { return _drop($r,"bad UA") }
		case 2 { return _ban($r,"bad UA") }
		case 3 { return _deny($r,"bad UA") }
	}
	switch(_scanner($r)){
		case 1 { return _drop($r,"scanner") }
		case 2 { return _ban($r,"scanner") }
		case 3 { return _deny($r,"scanner") }
	}
	return 0;
}
sub _static {
	my $r = shift;
	_prepare($r);
	if($r->uri =~ /\.php$/i){
		return _deny($r,"PHP on static");
	}
	return 0;
}
## get routine used for POST or GET request
sub _post {
	my $r = shift;
	if($r->has_request_body(\&_posthandle)){
		return 200;
	}
	return 0;
}
sub _posthandle {
	my $r = shift;
	_prepare($r);
	switch(_post_rules($r)){
		case 1 { return _drop($r,"POST intrusion") }
		case 2 { return _ban($r,"POST intrusion") }
		case 3 { return _deny($r,"POST intrusion") }
	}
	my $to = $r->variable("sec_path");
	$to =~ s/^([^,]+),.*$/$1/;
	$to =~ s/\/$//;
	$to .= $r->variable("request_uri");
	$r->internal_redirect($to);
}

sub _drop {
	my $r = shift;
	my $reason = shift;
	$r->send_http_header("text/html");
	_log($r,"drop",$reason);
	return 200;
}
sub _deny {
	my $r = shift;
	my $reason = shift;
	_log($r,"deny",$reason);
	return 403;
}
sub _ban {
	my $r = shift;
	my $reason = shift;
	$r->send_http_header("text/html");
	$r->print("You are hacker.\n");
	_log($r,"ban",$reason);
	return 200;
}
sub _log {
	my $r = shift;
	my $action = shift;
	my $reason = shift;
	my $file = $r->variable("sec_log_file");
	if ($file ne "") {
		my @ar = (
			time,
			$action,
			$reason,
			$r->variable("remote_addr"),
			$r->variable("host"),
			$r->header_in("referer"),
			$user_agent,
			$r->header_in("x-forwarded-for"),
			$uri,
		);
		my $string;
		foreach my $re (@ar){
			$re =~ s/;//g;
			$string .= $re.";"
		}
		if (open LOG, ">> $file"){
			print LOG $string."\n" ;
			close LOG;
		}
	}
}
sub _prepare {
	my $r = shift;
	$user_agent = $r->header_in("user-agent");
	$uri = $r->variable("request_uri");
	$combi =
		$uri.
		$r->variable("remote_addr").
		$r->variable("host").
		$r->header_in("referer").
		$user_agent.
		$r->header_in("x-forwarded-for");
	$combi = $r->unescape($combi);
	$combi =~ s/[\n\r\t]//g;
}
sub do {
	my $r = shift;
	my $path = $r->variable("sec_path");
	my $to = '';
	if($path =~ /^([^,]+),(.*)$/){
		$to = $1;
		$path = $2;
	}else{
		$to = $path;
		$path = '';
	}
	$to =~ s/\/$//;
	$to .= $r->variable("request_uri");
	
	foreach my $cmd (split /,/,$path){
		$r->header_out("path",$cmd) if DEBUG;
		if($cmd eq "special_chars"){
			$to =~ s/\(|%28/%26%2340;/g;
			$to =~ s/\<|%3c/%26lt;/ig;
			$to =~ s/\>|%3e/%26gt;/ig;
		}
		if($cmd eq "post"){
			my $ret = _post($r);
			return $ret if $ret;
		}
		if($cmd eq "common"){
			my $ret = _common($r);
			return $ret if $ret;
		}
		if($cmd eq "static"){
			$to =~ s/^([^?]*)\?.*$/$1/;
			my $ret = _static($r);
			return $ret if $ret;
		}
		if($cmd =~ /^js_protect\((.*)\)$/){
			my $ret = _js_protect($r,$1);
			return $ret if $ret;
		}
	}
	$r->internal_redirect($to);
}

1;

